
#pragma once

#include "Common/Math.h"
#include "Parameter.h"

using namespace System::ComponentModel;
using namespace System::Collections::Specialized;

namespace ttg_internal
{
	namespace utils
	{
		///<summary>
		/// Represnts named set of parameters with child sub-sets.
		///</summary>
		public ref class ParameterSet :public INotifyCollectionChanged
		{
			private:
				ParameterSet ^_owner;
				System::String ^_name;
				BindingList<Parameter ^> ^_parameters;
				BindingList<ParameterSet ^> ^_sets;
				ttg::math::uint64 _tag;
			internal:
				///<summary>
				/// Creates empty set.
				///</summary>
				ParameterSet(System::String ^name, ParameterSet ^owner)
				{
					_owner = owner;
					_name = name;
					_parameters = gcnew BindingList<Parameter ^>();
					_sets = gcnew BindingList<ParameterSet ^>();
				}
				///<summary>
				/// Notifies this set and onwer about changes.
				///</summary>
				void onChange(NotifyCollectionChangedAction action)
				{
					CollectionChanged(this, gcnew NotifyCollectionChangedEventArgs(action));
					if (_owner != nullptr)
						_owner->CollectionChanged(_owner, gcnew NotifyCollectionChangedEventArgs(action));
				}
				///<summary>
				/// Adds new parameter. Note: it is NOT thread-safe.
				///</summary>
				void addParameter(Parameter ^p)
				{
					_parameters->Add(p);
					//onChange(NotifyCollectionChangedAction::Add);
					onChange(NotifyCollectionChangedAction::Reset);
				}
				///<summary>
				/// Removes parameter. Note: it is NOT thread-safe.
				///</summary>
				void removeParameter(Parameter ^p)
				{
					_parameters->Remove(p);
					//onChange(NotifyCollectionChangedAction::Remove);
					onChange(NotifyCollectionChangedAction::Reset);
				}
				///<summary>
				/// Adds new set of parameters as child sub-set.
				/// Note: it is NOT thread-safe.
				///</summary>
				void addSubSet(ParameterSet ^set)
				{
					_sets->Add(set);
					//onChange(NotifyCollectionChangedAction::Add);
					onChange(NotifyCollectionChangedAction::Reset);
				}
				///<summary>
				/// Removes child sub-set. Note: it's not thread-safe.
				///</summary>
				void removeSubSet(ParameterSet ^set)
				{
					_sets->Remove(set);
					//onChange(NotifyCollectionChangedAction::Remove);
					onChange(NotifyCollectionChangedAction::Reset);
				}
				///<summary>
				/// Auxiliary tag, that is used for ID storing;
				///</summary>
				property ttg::math::uint64 Tag
				{
					ttg::math::uint64 get()
					{ return _tag; }
					void set(ttg::math::uint64 value)
					{ _tag = value; }
				}
			public:
				virtual event NotifyCollectionChangedEventHandler ^CollectionChanged;
				///<summary>
				/// Returns name of current set.
				///</summary>
				property System::String ^Name
				{
					System::String ^get()
					{ return _name; }
				}
				///<summary>
				/// Returns owner of current set (or nullptr).
				///</summary>
				property ParameterSet ^Owner
				{
					ParameterSet ^get()
					{ return _owner; }
				}
				///<summary>
				/// Returns parameters of current set.
				///</summary>
				property BindingList<Parameter ^> ^Parameters
				{
					BindingList<Parameter ^> ^get()
					{ return _parameters; }
				}
				///<summary>
				/// Returns child sub-sets with parameters.
				///</summary>
				property BindingList<ParameterSet ^> ^SubSets
				{
					BindingList<ParameterSet ^> ^get()
					{ return _sets; }
				}
		};
	}
}